import utils from "../../utils";
import page from "../../apis/page";
import {comsType} from "../../constants/form";
import {action, observable, toJS} from "mobx";
import {generateSubComponents, getDefaultData, getViewableComponent} from "../../components/designer/form/component";
import {getTheme} from "../../components/designer/form/theme";

const { FORM_HEADER, FORM_FOOTER } = comsType;
const defaultTheme = getTheme();

export default class ComponentStore {
  @observable formHeader = {};
  @observable formFooter = {};
  @observable components = null;
  @observable currCom = null;
  @observable theme = {};


  @action init = appid => {
    return page.getDesign(appid).then(all => {
      const coms = all.main;

      this.theme = all.style ? JSON.parse(all.style) : defaultTheme;
      const headerDefaultConfig = require("../../components/designer/form/component/form-header/data").default;
      const footerDefaultConfig = require("../../components/designer/form/component/form-footer/data").default;
      if (!coms || !coms.length) {
        this.formHeader = { uuid: utils.UUID(), type: FORM_HEADER, config: headerDefaultConfig };
        this.formFooter = { uuid: utils.UUID(), type: FORM_FOOTER, config: footerDefaultConfig };
        
        this.components = [];
      } else {
        // config为null时 组件的defaultData无法起效
        coms.forEach(com => com.config = com.config || {});

        this.formHeader = coms.find(com => com.type === FORM_HEADER);
        this.formFooter = coms.find(com => com.type === FORM_FOOTER);
        this.components = coms.filter(com => getViewableComponent(com)).map(com => {
          if(com.config.selected){
            this.currCom = com;
          }
          return com;
        });
      }
      return coms;
    });
  }

  @action onDragHover = (dragging, hovered) => {
    const len = this.components.length;
    const dIndex = this.findComponentIndex(dragging);

    if (!hovered) {
      if (dIndex >= 0) {
        this.removeComponent(dIndex);
      }

      return this.addComponentPlaceholder(dragging, len);
    }

    let hIndex = this.findComponentIndex(hovered);

    // 组件顺序为改变
    if (dIndex >= 0 && dIndex === hIndex - 1) return;

    // 组件顺序发生改变
    if (dIndex >= 0) {
      this.removeComponent(dIndex);
      hIndex = this.findComponentIndex(hovered);
    }

    // 更改placeholder位置
    this.addComponentPlaceholder(dragging, hIndex);
  }

  @action onDrop = (dragging, dropped) => {
    const dgIndex = this.findComponentIndex(dragging);
    let newIndex; // 新组件生成的index

    this.removeComponent(dgIndex);

    if (dropped) {
      if (dropped.placeholder) {
        newIndex = dgIndex;
      } else {
        newIndex = this.findComponentIndex(dropped);
      }
    } else {
      newIndex = this.components.length;
    }

    this.addComponent(dragging, newIndex);
  }

  // isNew 是否为新拖动的组件(并未渲染过View), drop out之后应该移除
  @action onDragEnd = (droppedOut, isNew) => {
    const index = this.findComponentIndex(droppedOut);

    if (index === -1) return;

    this.removeComponent(index);
    !isNew && this.addComponent(droppedOut, index);
  }

  // 避免使用memoize后 com被缓存无法及时更新的问题
  @action oncurrComChange = comUUID => {
    const coms = [...this.components, this.formFooter, this.formHeader];
    const currCom = coms.find(com => com.uuid === comUUID);

    this.currCom = currCom;
  }

  @action addComponentToBottom = newCom => {
    const len = this.currCom ? this.findComponentIndex(this.currCom)+1 : this.components.length;

    this.addComponent(newCom, len);
  }

  @action onPropsChange = (key, value) => {
    const index = this.findComponentIndex(this.currCom);
    const keys = key.split('.'); // 针对复杂的子对象 如:a.b
    const _setValue = obj => {
      const len = keys.length;

      keys.reduce((prev, key, index) => {
        if(len !== index + 1) return prev[key];

        prev[key] = value;
      }, obj);
    };

    if (index === -1) {
      const { uuid } = this.currCom;
      const type = uuid !== this.formFooter.uuid ? 'formHeader' : 'formFooter';

      _setValue(this[type].config);
      this[type] = toJS(this[type]);
      this.currCom = this[type];
      
      return;
    }

    _setValue(this.components[index].config);
    this.currCom = toJS(this.components[index]);

    this.components = toJS(this.components);
  }

  @action onRemove = com => {
    const index = this.findComponentIndex(com);

    this.removeComponent(index);
    
    if (this.currCom && com.uuid === this.currCom.uuid) {
      this.currCom = null;
    }
  }

  getComponents() {
    const coms = toJS(this.components);
    const allComs = [];

    coms.forEach(com => {
      com.name = com.config.title || '';
      com.config.selected = false;

      if (this.currCom && com.uuid === this.currCom.uuid) {
        com.config.selected = true;
      }
      allComs.push(com);

      // 复合组件 - 需要拆分子组件，便于后台生成多字段用于支持图表分析
      // 如地址
      if (com.config.complex) {
        const subComs = generateSubComponents(com);

        allComs.push(...subComs);
      }
    });

    allComs.unshift(toJS(this.formHeader));
    allComs.push(toJS(this.formFooter));

    return allComs;
  }

  removeComponent(index) {
    this.components.splice(index, 1);
  }

  findComponentIndex(item) {
    return this.components.findIndex(com => com.uuid === item.uuid);
  }

  addComponent(item, index) {
    const { type, name, uuid = utils.UUID(), config = getDefaultData(type) } = item;
    const newCom = { type, name, uuid, config };
    
    if (config.complex) {
      // 为复合组件的子组件初始化uuid
      config.complex.forEach(key => {
        const sub = config[key];

        sub.uuid = utils.UUID();
      });
    }

    this.components.splice(index, 0, newCom);
    this.currCom = newCom;
  }

  addComponentPlaceholder(item, index) {
    this.components.splice(index, 0, { ...item, placeholder: true });
  }
}